﻿using System;
using System.Collections.Generic;
using System.Linq;
using SlamCms.Common;

namespace SlamCms.Data
{
	[Serializable]
	public class TagTree : ICloneable
	{
		public string TagTreeId { get; set; }
		public string Title { get; set; }
		public int SortOrder { get; set; }

		[NonSerialized]
		public DataContext Context;

		public TagTreeNode Root { get; set; }

		public TagTreeNode FindNode(string id)
		{
			return this.FindNode(n => n.Id == id);
		}

		public TagTreeNode FindNode(Predicate<TagTreeNode> predicate)
		{
			if (predicate == null)
				throw new ArgumentNullException();

			if (this.Root == null)
				return null;

			return this.FindNode(this.Root, predicate);
		}

		public IEnumerable<TagTreeNode> FindNodes(Predicate<TagTreeNode> predicate)
		{
			if (predicate == null)
				throw new ArgumentNullException();

			if (this.Root == null)
				return new List<TagTreeNode>();

			return this.FindNodes(this.Root, predicate);
		}

		protected TagTreeNode FindNode(TagTreeNode node, Predicate<TagTreeNode> predicate)
		{
			return this.FindNodes(node, predicate).FirstOrDefault();
		}

		protected IEnumerable<TagTreeNode> FindNodes(TagTreeNode node, Predicate<TagTreeNode> predicate)
		{
			var result = new List<TagTreeNode>();

			if (predicate(node))
				result.Add(node);

			foreach (var childNode in node.Children)
			{
				var resultNodes = this.FindNodes(childNode, predicate);
				result.AddRange(resultNodes);
			}

			return result;
		}

		public object Clone()
		{
			return this.DeepClone();
		}
	}
}
